<?php


namespace App\Libraries\Source\Import;


use Illuminate\Support\Collection;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Exception;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Worksheet\RowIterator;

class OrderCollection
{
    /**
     * 订单
     */
    const orderEndCell = 'O';
    /**
     * @var string
     * @author luffyzhao@vip.126.com
     */
    const endCell = 'R';
    /**
     * @var \PhpOffice\PhpSpreadsheet\Spreadsheet
     * @author luffyzhao@vip.126.com
     */
    protected $spreadsheet;
    /**
     * @var \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
     * @author luffyzhao@vip.126.com
     */
    protected $worksheet;

    /**
     * 列转换
     * @var array
     */
    protected $columnKeyTransforms = [
        'A' => 'order_code',
        'B' => 'buyer_name',
        'C' => 'buyer_phone',
        'D' => 'buyer_id_number',
        'E' => 'receiving_name',
        'F' => 'receiving_phone',
        'G' => 'receiving_address',
        'H' => 'receiving_province',
        'I' => 'receiving_city',
        'J' => 'receiving_district',
        'K' => 'goods_value',
        'L' => 'tax',
        'M' => 'discount',
        'N' => 'freight',
        'O' => 'payment',
        'P' => 'sku',
        'Q' => 'quantity',
        'R' => 'price'
    ];


    /**
     * Check constructor.
     * @param $file
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     * @throws Exception
     * @author luffyzhao@vip.126.com
     */
    public function __construct($file)
    {
        $this->spreadsheet = IOFactory::load($file);
        $this->worksheet = $this->spreadsheet->getSheet(0);
    }

    /**
     * @throws \Exception
     * @author luffyzhao@vip.126.com
     */
    public function getOrder(): \Iterator
    {
        $rowIterator = $this->worksheet->getRowIterator(2);
        while ($rowIterator->valid()) {
            try {
                $merge = $this->handleMerge($rowIterator);
                if (empty($merge)) {
                    break;
                }

                yield $this->getOrderInfo($merge);

                $rowIterator->next();
            } catch (Exception $e) {
                new Exception(sprintf('第 【%d】 行,合并失败', $rowIterator->key()));
            }
        }
    }

    /**
     * @param RowIterator $rowIterator
     * @return array
     * @throws Exception
     * @throws \Exception
     * @author luffyzhao@vip.126.com
     */
    protected function handleMerge(RowIterator $rowIterator)
    {
        $startIndex = $rowIterator->key();
        $code = $this->worksheet->getCell('A' . $startIndex)->getValue();
        if (empty($code)) {
            return [];
        }
        $endIndex = $this->mergeNextRow($rowIterator, $code);
        $orderRowArr = [$startIndex, $endIndex];
        return $orderRowArr;
    }

    /**
     * @param RowIterator $rowIterator
     * @param $code
     * @return int
     * @throws Exception
     * @author luffyzhao@vip.126.com
     */
    protected function mergeNextRow(RowIterator $rowIterator, $code)
    {
        $index = $rowIterator->key();
        if ($this->worksheet->getCell('A' . ($index + 1))->getValue() == $code) {
            $rowIterator->next();
            if ($rowIterator->valid()) {
                $index = $this->mergeNextRow($rowIterator, $code);
            }
        }
        return $index;
    }

    /**
     * @param $merge
     * @return mixed
     * @throws \Exception
     * @author luffyzhao@vip.126.com
     */
    protected function getOrderInfo($merge)
    {
        list($start, $end) = $merge;
        $iterator = $this->worksheet->getRowIterator($start, $end);
        $orderEndColumnIndex = Coordinate::columnIndexFromString(self::orderEndCell);

        $orderInfo = [
            'products' => Collection::make()
        ];
        $product = [];
        $index = 0;
        while ($iterator->valid()) {
            $rowIterator = $iterator->current()->getCellIterator('A', self::endCell);
            while ($rowIterator->valid()) {
                if ($start === $iterator->key() && Coordinate::columnIndexFromString($rowIterator->key()) <= $orderEndColumnIndex) {
                    $orderInfo[$this->columnKeyTransform($rowIterator->key())] = $rowIterator->current()->getValue();

                } else if (Coordinate::columnIndexFromString($rowIterator->key()) > $orderEndColumnIndex) {
                    $product[$index][$this->columnKeyTransform($rowIterator->key())] = $rowIterator->current()->getValue();
                }
                $rowIterator->next();
            }
            $iterator->next();
            $index++;
        }

        $orderInfo['products'] = Collection::make($product);
        return Collection::make($orderInfo);
    }

    /**
     * @param $key
     * @return mixed|string
     * @author luffyzhao@vip.126.com
     */
    private function columnKeyTransform($key)
    {
        return $this->columnKeyTransforms[$key] ?? '';
    }
}